package calculation;

import java.util.Hashtable;

import database.RecordSearch;
import dbmanager.Column;
import dbmanager.DBManager;
import dbmanager.GetIdName;
import file.SearchRecord;

import sort.ArraySort;
import utility.Input;
import utility.ReadFile;
/**
 * /**
 * @author
 * TestExpression This class Produces the result of specified 
 *  calculation .
 */
 public class Expression 
{
	boolean FLAG= false;
	public String returnRecord="";
	public String TableId="";
	public String Expression="";
	public String Expressiontable="";
	GetIdName gin;
	DBManager dbSQL;
	String TABLENAME="tablename";
	//String MasterPath = "C://Reports//Basic_Reports//Master_Reports//";
	//String fileFormat = ".txt";
	ReadFile rFile = new ReadFile();
	
	//RandomAccessFile raf;
	int PVOrder = 0;
	int RefOrder = 0;
	//FileUtility file;
	/**
	 * Create Object of hashtable to put the value of expression
	 */ 
	public Hashtable<Object,Object> TransactionMap = new Hashtable<Object,Object>(); 
	public Hashtable<Object,Object>TransactionDetailMap =  new Hashtable<Object,Object>();
	
	public Expression(DBManager dbSQL, Hashtable<Object,Object> TransactionMap, Hashtable<Object,Object>TransactionDetailMap) 
	{
		this.dbSQL = dbSQL;
		gin = new GetIdName(dbSQL);
		TABLENAME = gin.getId(TABLENAME);
		this.TransactionMap.putAll(TransactionMap);
		this.TransactionDetailMap.putAll(TransactionDetailMap);
	}
	/**
	 * Expression() This is parametrise constructor 
	 * @param db Get the referenced of DBManager  
	 */
	public Expression(DBManager db) {
		
		this.dbSQL = db;
		gin = new GetIdName(dbSQL);
	}
/**
 * setExpression() This method is used to set the value of expression
 * @param expression_id Gets the String value of expression
 * @exception Exception
 */ 
	public boolean setExpression(String expression_id)
	{
		try 
		{
			String value_id = gin.getId("Value");
			String Return_id = gin.getId("Return");
			System.out.println("calculation::Calculation::getExpression()::Expression : "+expression_id);
			RecordSearch rs=new RecordSearch(dbSQL);
			Hashtable<Object, Object> hasht = new Hashtable<Object, Object>();
			hasht.clear();
			hasht.put("mid", expression_id);
			hasht.put("pid",value_id);
			hasht.put("td", "null");
			rs.setConditionMap(hasht);
			String exp[] = rs.getArrayFromResultSet();
			int VTOrder=0;
			String Values[] = exp[0].split("\t");
			try
			{
				//raf = new RandomAccessFile(trans_type_path,"r");
				//FileUtility file = new FileUtility(raf);
				//VTOrder = file.getColumnIndex("VT")-1;
				VTOrder = Column.vt_index-1; 
				//raf.close();
			}
			catch (Exception e) 
			{
				e.printStackTrace();
			}
			Expression = Values[VTOrder];
			System.out.println("calculation::Calculation::getExpression():: Expression : "+Expression);
			
			hasht.clear();
			hasht.put("mid", expression_id);
			hasht.put("pid", TABLENAME);
			rs.setConditionMap(hasht);
			String temp = rs.getArrayFromResultSet()[0];
			String temprecord[] = temp.split("\t");
			Expressiontable = temprecord[Column.pv_index-1];
			if(Expressiontable.equals("0"))
				Expressiontable = temprecord[Column.vt_index-1];
			else
				Expressiontable = gin.getItem(Expressiontable);
			hasht.clear();
			hasht.put("mid", expression_id);
			hasht.put("pid", Return_id);
			rs.setConditionMap(hasht);
			temp = rs.getArrayFromResultSet()[0];
			temprecord = temp.split("\t");
			
			int index = temprecord[VTOrder].indexOf(">");
			TableId = temprecord[VTOrder].substring(0,index);
			returnRecord = temprecord[Column.pv_index-1];
			if(returnRecord.equals("0"))
				returnRecord = temprecord[VTOrder].substring(index+1);
			else
			{
				returnRecord = gin.getItem(returnRecord);
				returnRecord = returnRecord.substring(index+1);
			}
			
			return true;
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
			return false;
		}
		//Return Value
	}
	/**
	 *parse() This method is used to parse the value of expression
	 * @param Expression Gets the String value of expression
	 * @exception Exception
	 * @return double value of expression
	 */ 
	public double parse(String Expression)
	{
		Expressionsubstring expSub = new Expressionsubstring(dbSQL,TransactionMap,TransactionDetailMap);
		String SplitChar = "!";
		
		System.out.println("calculation::Expression::parse(): Expression : "+Expression);
		String Precedence_id = gin.getId("OperatorPrecedence");
		String Operator_id = gin.getId("Operator");
		Hashtable<Object, Object> condition =new Hashtable<Object, Object>();
		condition.put("mid",Precedence_id);
		condition.put("td", "null");
		RecordSearch rs =new RecordSearch(dbSQL);
		rs.setConditionMap(condition);
		String result[] = rs.getArrayFromResultSet();
		StringBuffer Record = rFile.searchObject(result, Operator_id, SplitChar);
		
		try
		{
			//raf = new RandomAccessFile(trans_type_path,"r");
			//file = new FileUtility(raf);
			//PVOrder = file.getColumnIndex("PV")-1;
			//RefOrder = file.getColumnIndex("Ref")-1;;
			PVOrder = Column.pv_index-1;
			RefOrder = Column.ref_index-1;
		}
		catch (Exception e) 
		{
			e.printStackTrace();
			System.out.println("calculation::Expression::Parse(): Order of Property Details are not found");
		}
		int precedenceOrder=1;
		
		ArraySort sort = new ArraySort(dbSQL);
		String [] RecordSet = sort.sortArrayIndex(Record.toString().split(SplitChar),RefOrder);
		for(int i=0;i<RecordSet.length;i++)
		{
		
			String [] Values = RecordSet[i].split("\t");
			RecordSet[i]= gin.getItem(Values[PVOrder]);
			//System.out.println("Sorted Operators are : "+recordSet);
		}
		
		for(int i=0;i<RecordSet.length;i++)
		{
			String Operator = RecordSet[i];
			System.out.println("calculation::Expression::parse(): The Operator is : "+Operator);
			if(i < 1)
			{
				int beginIndex =0;
				String temp = Expression;
				while(true)
				{
					if(temp.contains(Operator))
					{
						int start =  temp.indexOf(Operator);
						beginIndex = beginIndex+start+1;
						temp = temp.substring(start+1);
						if(temp.contains(Operator))
						{
							continue;
						}
						else
						{
							int end = temp.indexOf(RecordSet[i+1]);
							temp = temp.substring(0, end);
							System.out.println("calculation::Expression::parse(): The String is : "+RecordSet[i]+temp+RecordSet[i+1]);
							
							//System.out.println("calculation::Expression::parse(): Begining Index is : "+beginIndex);
							end = beginIndex+end;
							//System.out.println("calculation::Expression::parse(): End Index is : "+end);
							System.out.println("calculation::Expression::parse():The Exp is : "+Expression.substring(beginIndex-1,end+1));
							
							StringBuffer expression = new StringBuffer(Expression);
							String replace = expSub.getResult(temp, RecordSet);
							expression.replace(beginIndex-1, end+1, replace);
							Expression = expression.toString();
							
							// Check if the calculation is completed or not
							try
							{
								FLAG = true;
								Double.parseDouble(Expression);
								return Double.parseDouble(Expression);
							}
							catch (Exception e) 
							{
								FLAG = false;
							}
							if(FLAG == false)
							{
								System.out.println("calculation::Expression::parse():Call Expression : "+Expression);
								parse(Expression);
							}
							System.out.println("calculation::Expression::parse():The New Expression String is : "+Expression);
						}
					}
					else 
					{
						precedenceOrder = precedenceOrder+2;
						break;
					}
				}
			}
			else
			{
				Expression = expSub.getResult(Expression, RecordSet);
				//Check if the calculation is completed or not
				try
				{
					Double.parseDouble(Expression);
					return Double.parseDouble(Expression);
				}
				catch (Exception e) 
				{
					e.printStackTrace();
				}
				if(Expression.equals("error"))
				{
					System.out.println("calculation::Expression::parse():Error Occured : ");
					return 0;
				}
			}
		}
		return Double.parseDouble(Expression);
	}

/*	private String [] OperatorSorting(String[] recordSet)
	{
		String [] sortedOperators = recordSet;
		for(int j=0;j<recordSet.length;j++)
		{
			String []Values = recordSet[j].split("\t");
			int Precedence = Integer.parseInt(gin.getItem(Values[RefOrder]));
			int min = Precedence;
			for(int i=j+1;i<recordSet.length;i++)
			{
				Precedence = Integer.parseInt(gin.getItem(Values[RefOrder]));
				if(min < Precedence)
				{
					String temp = recordSet[j];
					recordSet[j] = recordSet[i];
					recordSet[i] = temp;
					min = Precedence;
				}
			}
		}
		for(int i=0;i<recordSet.length;i++)
		{
		
			String [] Values = recordSet[i].split("\t");
			sortedOperators[i]= gin.getItem(Values[PVOrder]);
			//System.out.println("Sorted Operators are : "+recordSet);
		}
		return sortedOperators;
	}
*/	
	public static void main(String [] a)
	{
		DBManager db = new DBManager();
		db.getConnect();
		Expression exp = new Expression(db);
		System.out.println(exp.parse("2222+4444*111/222"));
	}
}

